#include "utils.hpp"
#include "Real.hpp"

/* 
 * Método de Machin para calcular PI
 * =================================
 * Cálculo:
 * PI / 4 = 4*arctan(1/5) - arctan(1/239)
 *
 * arctan(x) = Sum_n=0^inf[ (-1)^n x^(2n+1)/(2n+1) ] cuando |x| < 1
 */
template<typename T>
T arctan( T x, Iteration iterations )
{

	T    result = 0.0f; // resultado
	bool add    = true; // true si próxima operación es una suma

	// sumatoria desde 0 a la cantidad de iteraciones elegida
	for( Iteration n = 0 ; n < iterations ; n++ )
	{

		unsigned long long y = (2*n+1);

		// calcula el término n de la serie
		T term = pow(x,y)/static_cast<T>(y);

		// este if juega el papel del (-1)^n y suma o resta
		// según el caso correspondiente
		if( add )
			result += term;
		else	
			result -= term;

		// cambia la próxima operación de suma a resta
		add = !add;

	}

	return result;

}

template<typename T>
T machin( Iteration iterations )
{

	return static_cast<double>(16.0f)*arctan<T>( 0.2f, iterations ) -
	       static_cast<double>(4.0f)*arctan<T>( 0.0041841004184100415f, iterations );

}

int main(int argc, char** argv)
{
	
	return run( &machin<Real>, 5000, argc, argv );

}

